'use strict';

const createConfig = require('uni-config-center');
const uidConfig = createConfig({
	pluginId: 'uni-id'
});

const uidPay = require('uni-pay');

const {
	wxmpapi
} = require('use-api');

const {
	Controller
} = require('uni-cloud-router');
const dbcmd = uniCloud.database().command;
const $ = dbcmd.aggregate;

module.exports = class OrderController extends Controller {
	// 订单列表
	async orderList() {
		const response = {
			code: 1,
			total: 0,
			datas: []
		};

		let {
			page,
			rows,
			group,
			orderby,
			state,
			order_id,
			order_member_name,
			order_member_mobile,
			order_consignee,
			order_consignee_tel,
			order_pay_way,
			begin_time,
			end_time
		} = this.ctx.data;

		const whereObj = {
			is_delete: 0
		};

		// 状态
		if (state != '全部') {
			whereObj.state = state;
		}

		// 订单ID
		if (order_id) {
			whereObj.order_id = new RegExp(this.service.utils.filterRegexpKey(order_id), 'i');
		}
		// 下单人
		if (order_member_name) {
			whereObj.order_member_name = new RegExp(this.service.utils.filterRegexpKey(order_member_name), 'i');
		}
		// 下单人手机号
		if (order_member_mobile) {
			whereObj.order_member_mobile = new RegExp(this.service.utils.filterRegexpKey(order_member_mobile),
				'i');
		}
		// 收货人
		if (order_consignee) {
			whereObj.order_consignee = new RegExp(this.service.utils.filterRegexpKey(order_consignee), 'i');
		}
		// 收货人手机号
		if (order_consignee_tel) {
			whereObj.order_consignee_tel = new RegExp(this.service.utils.filterRegexpKey(order_consignee_tel),
				'i');
		}
		// 支付方式
		if (order_pay_way) {
			whereObj.order_pay_way = order_pay_way;
		}
		// 下单时间
		if (begin_time && end_time) {
			whereObj.create_time = dbcmd.gte(begin_time).and(dbcmd.lte(end_time));
		}

		// 分组状态数量
		let groupWhereObj = Object.assign({}, whereObj);
		delete groupWhereObj[group.field];

		const groupRes = await this.db.collection('usemall-order')
			.aggregate()
			.match(groupWhereObj)
			.group({
				_id: '$' + group.field,
				cnt: $.sum(1)
			})
			.end();

		if (groupRes && groupRes.data) {
			response.groupDatas = groupRes.data;
			group.datas = [];
			group.total = 0;

			for (let key in group.obj) {
				group.obj[key] = 0;
			}

			response.groupDatas.forEach(x => {
				if (Object.keys(group.obj).includes(x._id + "")) {
					group.obj[x._id] = x.cnt;
					group.total += x.cnt;
				}
			})
			if (Object.keys(group.obj).includes('全部')) {
				group.obj['全部'] = group.total;
			}

			for (let key in group.obj) {
				group.datas.push({
					name: key,
					cnt: group.obj[key]
				})
			}
			response.group = group;
		}

		// 总数
		const countRes = await this.db.collection('usemall-order').where(whereObj).count();
		response.total = countRes.total;

		// 排序
		orderby = orderby.split(' ');

		const res = await this.db.collection('usemall-order')
			.where(whereObj)
			.orderBy(orderby[0], orderby[1])
			.field({
				order_id: true,
				order_member_headimg: true,
				order_member_name: true,
				order_total_money: true,
				order_actural_paid: true,
				order_goods_cnt: true,
				order_type: true,
				state: true,
				order_member_mobile: true,
				order_way: true,
				order_pay_way: true,
				order_consignee: true,
				order_consignee_tel: true,
				order_from: true,
				is_fxs: true,
				last_modify_time: true,
				create_time: true
			})
			.skip((page - 1) * rows)
			.limit(rows)
			.get();

		// 判断环境
		const isDevelopment = uidConfig.config('env') === 'dev';

		res.data.forEach(x => {
			// 测试环境下 进行脱敏处理
			if (isDevelopment) {
				x.order_member_mobile = this.service.utils.desz(x.order_member_mobile);
				x.order_consignee = this.service.utils.desz(x.order_consignee);
				x.order_consignee_tel = this.service.utils.desz(x.order_consignee_tel);
			}
		});

		response.code = 0;
		response.datas = res.data;
		return response;
	}

	// 订单详情
	async orderDetail() {
		const response = {
			code: 1,
			total: 0,
			datas: {}
		};

		const {
			id
		} = this.ctx.data;

		const whereObj = {
			order_id: id
		};

		const orderLogRes = await this.db.collection('usemall-order-log')
			.where(whereObj)
			.orderBy('create_time', 'asc')
			.field({
				log_type: true,
				create_time: true
			})
			.limit(30)
			.get();

		const orderRes = await this.db.collection('usemall-order')
			.where(whereObj)
			.field({
				order_id: true,
				order_invoice_id: true,
				order_member_openid: true,
				order_member_headimg: true,
				order_member_name: true,
				order_member_mobile: true,
				order_consignee: true,
				order_consignee_addr: true,
				order_consignee_addr_detail: true,
				order_consignee_tel: true,
				order_type: true,
				order_express: true,
				order_express_no: true,
				order_pay_no: true,
				order_pay_way: true,
				order_pay_original: true,
				order_pay_state: true,
				order_total_money: true,
				order_total_cnt: true,
				order_way: true,
				order_info: true,
				order_goods_cnt: true,
				order_actural_paid: true,
				order_from: true,
				order_coupon_id: true,
				order_coupon: true,
				order_refund_state: true,
				order_refund_reason: true,
				order_refund_desc: true,
				order_refund_remark: true,
				state: true,
				remark: true
			})
			.get();

		const [order] = orderRes.data;

		const isDevelopment = uidConfig.config('env') === 'dev';

		// 测试环境下 进行脱敏处理
		if (isDevelopment) {
			order.order_member_mobile = this.service.utils.desz(order.order_member_mobile);
			order.order_consignee = this.service.utils.desz(order.order_consignee);
			order.order_consignee_tel = this.service.utils.desz(order.order_consignee_tel);
		}

		response.code = 0;
		response.datas.logs = orderLogRes.data;
		response.datas.order = order;
		return response;
	}

	// 改价
	async changePrice() {
		let response = {
			code: 1
		};

		let {
			id,
			price,
			remark
		} = this.ctx.data;

		if (!id) {
			this.throw(`订单ID不存在`);
		}

		// 单位为分，取整数
		price = parseInt(price);
		if (!price || price <= 0) {
			this.throw(`改价金额需大于0`);
		}

		// 1. 获取订单数据
		const orderRes = await this.db.collection('usemall-order').doc(id).field({
			order_id: true,
			state: true,
			is_fxs: true,
			order_vip: true,
			order_fxs_uid: true,
			order_fxs_uid2: true,
			order_return_integral: true,
			order_pay_state: true,
			order_goods_money: true,
			order_total_money: true,
			order_actural_paid: true,
			order_discount: true
		}).get();
		const [order] = orderRes.data;
		if (!(order && order._id)) {
			this.throw(`订单[${id}]不存在`);
		}

		if (!(order.state == '待付款' && order.order_pay_state == '待付款')) {
			this.throw(`当前订单状态不支持改价`);
		}

		// 需付款
		const oldActuralPaid = order.order_actural_paid;

		// 2.1 计算实付款金额、优惠金额
		// 实付款
		order.order_actural_paid = price;
		// 优惠金额
		order.order_discount = 0;
		if (order.order_total_money > price) {
			// 计算优惠金额
			order.order_discount = order.order_total_money - price;
		}

		// 修改订单
		const orderUpdateObj = {};
		// 2.2 计算分销佣金
		if (order.is_fxs == '是') {
			// 查询订单详情
			const orderDetailRes = await this.db.collection('usemall-order-detail').where({
				order_id: order.order_id
			}).get();
			const orderDetails = orderDetailRes.data;
			const promises = [];

			// 分销商佣金
			orderUpdateObj.order_fxs_amount = 0;
			orderUpdateObj.order_fxs_amount2 = 0;
			// 计算每款商品的分销佣金，上级佣金、上上级佣金
			orderDetails.forEach(x => {
				// 修改订单详情数据
				const orderDetailUpdateObj = {};
				// 优惠比例
				let discount_ratio = 1;
				// 判断付款金额是否存在优惠
				if (order.order_actural_paid !== order.order_total_money && order.order_discount) {
					discount_ratio = this.service.utils.fmtFloat(order.order_actural_paid / order
						.order_total_money);
				}

				// 商品金额
				x.goods_amount = this.service.utils.fmtInt(x.goods_price * x.goods_num *
					discount_ratio);
				// 商品折扣
				x.goods_discount = x.goods_price * x.goods_num - x.goods_amount;

				if (x.is_fxs == '是') {
					// frmInt int 格式化，防止 js 精度丢失
					if (Boolean(order.order_fxs_uid)) {
						// 上级返利金额
						x.fxs_amount = this.service.utils.fmtInt(x.goods_amount * (x.rebate_ratio /
							100));
						orderUpdateObj.order_fxs_amount += x.fxs_amount;
						orderDetailUpdateObj.fxs_amount = x.fxs_amount;
					}
					if (Boolean(order.order_fxs_uid)) {
						// 上上级返利金额
						x.fxs_amount2 = this.service.utils.fmtInt(x.goods_amount * (x.rebate_ratio2 /
							100));
						orderUpdateObj.order_fxs_amount2 += x.fxs_amount2;
						orderDetailUpdateObj.fxs_amount2 = x.fxs_amount2;
					}
				}

				orderDetailUpdateObj.goods_amount = x.goods_amount;
				orderDetailUpdateObj.goods_discount = x.goods_discount;

				promises.push(
					this.db.collection('usemall-order-detail').doc(x._id).update(
						orderDetailUpdateObj)
				);
			});

			if (promises.length) {
				await Promise.all(promises);
			}
		}

		// 2.3 计算返多少积分
		if (order.order_actural_paid) {
			// 获取会员设置项
			const memberParameter = this.db.collection('usemall-member-parameter').limit(1).field({
				desc: false,
				vip_desc: false
			}).get();
			// 获取积分设置项
			const integralParameter = this.db.collection('usemall-integral-parameter').limit(1).field({
				integral_desc: false
			}).get();
			const [memberParameterRes, integralParameterRes] = await Promise.all([memberParameter,
				integralParameter
			]);
			const [memberSetting] = memberParameterRes.data;
			const [integralSetting] = integralParameterRes.data;

			let integralTotal = 0;
			if (integralSetting && integralSetting.return_integral_ratio > 0) {
				// 计算下单实付款返积分比例
				integralTotal = this.service.utils.fmtInt((order.order_actural_paid / 100) * (integralSetting
					.return_integral_ratio));
			}
			if (order.order_vip && memberSetting && memberSetting.vip_integral_mul > 0 && integralTotal > 0) {
				// VIP订单，计算 VIP 返积分比例
				integralTotal *= memberSetting.vip_integral_mul;
			}
			// 返多少积分
			orderUpdateObj.order_return_integral = integralTotal
		}

		// 3. 修改订单数据
		await this.db.collection('usemall-order')
			.doc(order._id)
			.update({
				...orderUpdateObj,

				order_actural_paid: order.order_actural_paid,
				order_discount: order.order_discount,
				order_remark: remark,

				last_modify_uid: this.ctx.auth.uid,
				last_modify_uname: this.ctx.auth.userInfo.username,
				last_modify_time: Date.now()
			});

		// 4. 记录订单日志
		await this.db.collection('usemall-order-log').add({
			order_id: order.order_id,
			log_type: '改价',
			current_state: '待付款',
			prev_state: '待付款',
			remark: `改价前: ${oldActuralPaid / 100}元，改价后: ${price / 100}元。备注：${remark || '--'}`,
			ip: this.ctx.context.CLIENTIP,
			is_delete: 0,
			create_uid: this.ctx.auth.uid,
			create_uname: this.ctx.auth.userInfo.username,
			create_time: Date.now()
		});

		response.code = 0;
		response.msg = '改价成功';

		return response;
	}

	// 发货
	async delivery() {
		let response = {
			code: 1,
		};

		const {
			id,
			expressForm,
			isWxExpress
		} = this.ctx.data;

		const uid = this.ctx.auth.uid;

		const orderRes = await this.db.collection('usemall-order').doc(id).get();
		const [order] = orderRes.data;

		if (!(order && order._id)) {
			response.msg = `此发货订单不存在`;
			return response;
		}

		let express = '';
		if (expressForm.order_type == '发货订单') {
			const expressRes = await this.db.collection('usemall-order-express').doc(expressForm.express_id)
				.field({
					name: true,
					encoding: true,
					wx_encoding: true
				}).get();
			[express] = expressRes.data;
		}

		const userRes = await this.db.collection('uni-id-users').doc(order.create_uid).field({
			wx_openid: true,
			wx_unionid: true
		}).get();
		const [user] = userRes.data;

		let openid = '';
		if (user && user.wx_openid) {
			openid = user.wx_openid['mp-weixin'];
		}

		let order_wxmp_delivery = 0;
		if (isWxExpress) {
			if (!order.order_pay_openid) {
				order.order_pay_openid = openid;
			}

			const wxDeliveryRes = await this.wxDelivery(order, express, expressForm);
			if (wxDeliveryRes.errcode === 48001) {
				response.msg = '当前小程序未开通发货信息，请关闭同步微信发货后重试';
				return response;
			}

			if (wxDeliveryRes.errcode) {
				response.msg = wxDeliveryRes.errmsg;
				return response;
			}
			order_wxmp_delivery = 1;
		}

		try {
			let title = order.group_id ? `拼团订单 ${order.order_id} 已发货` : `订单：${order.order_id} 已发货，请留意物流信息`;
			let desc = `${expressForm.order_type} - ${express.name}:${expressForm.express_no}`;

			if (expressForm.order_type === '虚拟订单') {
				title = order.group_id ? `拼团订单 ${order.order_id} 已发货` : `订单：${order.order_id} 已发货`;
				desc = `${expressForm.order_type}`;
			}

			if (user && user.wx_openid) {
				openid = user.wx_openid['h5-weixin'];
			}

			// 待发货通知 102
			// 不需要 await，只需发送请求即可
			uniCloud.httpclient.request(`${uidConfig.config('message-notify.url')}/102`, {
				method: 'post',
				headers: {
					'message-notify-key': uidConfig.config('message-notify.key')
				},
				data: {
					id: order.order_id,
					openid: openid,
					scene: 102,
					uname: order.order_member_name,
					title: title,
					type: desc,
					goods: `${order.order_info}`,
					remark: '查看详情'
				},
				contentType: 'json',
				dataType: 'json'
			});
		} catch (e) {
			console.log('message-notify err', e);
		}

		// 修改订单数据
		await this.db.collection('usemall-order').doc(id).update({
			order_wxmp_delivery: order_wxmp_delivery,
			order_type: expressForm.order_type,
			order_express: express.name,
			order_express_com: express.encoding,
			order_wx_express_com: express.wx_encoding,
			order_express_no: expressForm.express_no,
			state: expressForm.state,
			deliver_time: Date.now(),
			last_modify_uid: uid,
			last_modify_uname: this.ctx.auth.userInfo.username,
			last_modify_time: Date.now()
		});

		// 判断是 实物订单 还是 虚拟订单
		let remark = '快递公司：' + express.name + '<br/>' +
			' 快递单号：' + expressForm.express_no;

		if (expressForm.order_type == '虚拟订单') {
			remark = '虚拟订单，确认发货';
		}

		// 添加订单日志
		await this.db.collection('usemall-order-log').add({
			order_id: order.order_id,
			log_type: '商家发货',
			current_state: '待收货',
			prev_state: '待发货',
			remark: remark,
			ip: this.ctx.context.CLIENTIP,
			create_uid: uid,
			create_time: Date.now(),
			create_uname: this.ctx.auth.userInfo.username
		});

		response.code = 0;
		response.msg = '发货成功';
		return response;
	}

	// 同步微信发货
	async wxDelivery(order, express, expressForm) {
		let logistics_type = 3;
		let deliveryObj = {
			delivery_mode: 1,
			shipping_list: [{
				item_desc: order.order_info.slice(0, 118)
			}]
		};

		if (expressForm.order_type == '发货订单') {
			logistics_type = 1;
			deliveryObj = {
				// 1、UNIFIED_DELIVERY（统一发货）2、SPLIT_DELIVERY（分拆发货） 示例值: UNIFIED_DELIVERY
				delivery_mode: 1,
				shipping_list: [{
					tracking_no: expressForm.express_no,
					express_company: express.wx_encoding,
					item_desc: order.order_info.slice(0, 118),
					contact: {
						receiver_contact: order.order_consignee_tel
					}
				}]
			}
		}

		const res = await wxmpapi.upload_shipping_info({
			order_key: {
				order_number_type: 2,
				transaction_id: order.order_pay_no
			},
			// 1、实体物流配送采用快递公司进行实体物流配送形式 2、同城配送 3、虚拟商品，虚拟商品，例如话费充值，点卡等，无实体配送形式 4、用户自提
			logistics_type: logistics_type,
			...deliveryObj,
			upload_time: new Date().toISOString(),
			payer: {
				openid: order.order_pay_openid
			}
		});

		return res;
	}

	// 已收货
	async received() {
		let response = {
			code: 1,
		};
		const start = Date.now();
		const nowdate = start;

		const {
			order_id,
			state
		} = this.ctx.data;

		const uid = this.ctx.auth.uid;

		let where_obj = {
			is_delete: 0,
			order_id: order_id
		};

		let orderRes = await this.db.collection('usemall-order')
			.where(where_obj)
			.field({
				order_actural_paid: true,
				order_id: true,
				is_fxs: true,
				is_settlement: true,
				order_fxs_uid: true,
				order_fxs_amount: true,
				order_fxs_uid2: true,
				order_fxs_amount2: true,
				order_member_name: true,
				order_member_openid: true,
				order_member_headimg: true,
				order_info: true,
				order_goods_cnt: true,
				create_uid: true
			})
			.get();

		if (!(orderRes && orderRes.data && orderRes.data.length == 1)) {
			response.msg = `订单[${order_id}]不存在`;
			return response;
		}

		const [order] = orderRes.data;

		let orderUpdate = {
			state: state,
			received_time: nowdate,
			last_modify_time: nowdate,
			last_modify_uname: this.ctx.auth.userInfo.username,
			last_modify_uid: uid
		};

		// 获取分销配置
		const distributorParameterRes = await this.db.collection('usemall-distributor-parameter')
			.field({
				settlement_type: true
			})
			.get();

		const [distributorParameter] = distributorParameterRes.data;

		// 分销结算
		if (distributorParameter.settlement_type == 1 && order.is_fxs == '是' && order.is_settlement == '否') {
			// 上级
			if (order.order_fxs_uid && order.order_fxs_amount) {
				// 1. 分销商可提现金额
				await this.db.collection('usemall-distributor').doc(order.order_fxs_uid).update({
					fxs_unsettled_amount: this.db.command.inc(-order.order_fxs_amount),
					fxs_cashout_amount: this.db.command.inc(order.order_fxs_amount),
					version: this.db.command.inc(1),

					last_modify_uid: uid,
					last_modify_uname: this.ctx.auth.userInfo.username,
					last_modify_time: nowdate
				});
				// 2. 分销记录状态 已结算
				await this.db.collection('usemall-distributor-record').where({
					fxs_uid: order.order_fxs_uid,
					order_id: order.order_id
				}).update({
					version: this.db.command.inc(1),
					state: '已结算',

					last_modify_uid: uid,
					last_modify_uname: this.ctx.auth.userInfo.username,
					last_modify_time: nowdate
				});

				// 3. 分销操作日志
				await this.db.collection('usemall-distributor-log').add({
					fxs_uid: order.order_fxs_uid,
					oper_content: `结算订单[+${order.order_id}]收益`,
					oper_type: '下单收益',
					oper_ip: this.ctx.context.CLIENTIP,
					remark: `下级会员[${order.order_member_name}]下单[+${order.order_fxs_amount / 100}]`,
					version: 1,
					is_delete: 0,
					create_uid: uid,
					create_uname: this.ctx.auth.userInfo.username,
					create_time: nowdate
				});
			}

			// 上上级
			if (order.order_fxs_uid2 && order.order_fxs_amount2) {
				// 1. 分销商可提现金额
				await this.db.collection('usemall-distributor').doc(order.order_fxs_uid2).update({
					fxs_unsettled_amount2: this.db.command.inc(-order.order_fxs_amount2),
					fxs_cashout_amount2: this.db.command.inc(order.order_fxs_amount2),
					version: this.db.command.inc(1),

					last_modify_uid: uid,
					last_modify_uname: this.ctx.auth.userInfo.username,
					last_modify_time: nowdate
				});
				// 2. 分销记录状态 已结算
				await this.db.collection('usemall-distributor-record').where({
					fxs_uid: order.order_fxs_uid2,
					order_id: order.order_id
				}).update({
					version: this.db.command.inc(1),
					state: '已结算',

					last_modify_uid: uid,
					last_modify_uname: this.ctx.auth.userInfo.username,
					last_modify_time: nowdate
				});

				// 3. 分销操作日志
				await this.db.collection('usemall-distributor-log').add({
					fxs_uid: order.order_fxs_uid2,
					oper_content: `结算订单[+${order.order_id}]收益`,
					oper_type: '下单收益',
					oper_ip: this.ctx.context.CLIENTIP,
					remark: `下下级会员[${order.order_member_name}]下单[+${order.order_fxs_amount2 / 100}]`,
					version: 1,
					is_delete: 0,
					create_uid: uid,
					create_uname: this.ctx.auth.userInfo.username,
					create_time: nowdate
				});
			}

			// 4. 分销订单已结算
			orderUpdate.is_settlement = '是';
			orderUpdate.settlement_time = nowdate;
		}

		const orderUpdateRes = await this.db.collection('usemall-order')
			.doc(order._id)
			.update(orderUpdate);

		if (orderUpdateRes && orderUpdateRes.updated == 1) {
			const order_log = {
				order_id: order.order_id,
				log_type: '已收货',
				current_state: state,
				prev_state: '待收货',
				ip: this.ctx.context.CLIENTIP,
				is_delete: 0,
				create_uid: uid,
				create_uname: this.ctx.auth.userInfo.username,
				create_time: nowdate
			};
			await this.db.collection('usemall-order-log').add(order_log);
		}

		response.datas = orderUpdateRes;

		const end = new Date().getTime();
		console.log(`耗时：${end - start}ms`);
		response.code = 0;
		response.msg = `耗时：${end - start}ms`;
		return response;
	}

	// 查看订单物流
	async orderExpress() {
		let response = {
			code: 1,
			msg: '物流轨迹查询失败'
		};

		const {
			order_id
		} = this.ctx.data;

		if (!order_id) {
			response.msg = '订单号不存在';
			return response;
		}

		// 查询订单数据
		const orderRes = await this.db.collection('usemall-order').where({
			order_id
		}).field({
			order_id: true,
			order_express: true,
			order_express_no: true,
			order_express_com: true,
			order_consignee_tel: true,
			order_express_datas: true
		}).get();

		if (!orderRes || orderRes.data.length !== 1) {
			response.msg = '订单不存在';
			return response;
		}

		const order = orderRes.data[0];

		// 存在有数据直接返回 express datas
		if (order.order_express_datas) {
			response.code = 0;
			response.msg = '物流轨迹查询成功';
			response.datas = order.order_express_datas;
			response.datas.company = order.order_express_com;

			return response;
		}

		if (!order.order_express_no) {
			response.msg = '快递单号不存在';

			return response;
		}

		// 调用快递100 实时快递查询接口
		const kd100Res = await this.service.express.kd100Query({
			"com": order.order_express_com || this.service.express.getKd100Com(order.order_express),
			"num": order.order_express_no,
			"phone": order.order_consignee_tel
		});

		response.datas = kd100Res;
		response.datas.company = order.order_express_com;
		response.msg = response.datas.message;

		if (response.datas && response.datas.message == "ok") {
			response.code = 0;

			/**
			 * 快递单状态
			 0 在途 快件处于运输过程中
			 1 揽收 快件已由快递公司揽收
			 2 疑难 快递100无法解析的状态，或者是需要人工介入的状态， 比方说收件人电话错误。
			 3 签收 正常签收
			 4 退签 货物退回发货人并签收
			 5 派件 货物正在进行派件
			 6 退回 货物正处于返回发货人的途中
			 7 转投 货物转给其他快递公司邮寄
			 10 待清关 货物等待清关
			 11 清关中 货物正在清关流程中
			 12 已清关 货物已完成清关流程
			 13 清关异常 货物在清关过程中出现异常
			 14 拒签 收件人明确拒收
			 */
			if (['3', '4', '14'].includes(response.datas.state)) {
				// 签收 退签 拒签
				// 写入订单物流轨迹数据
				await this.db.collection('usemall-order').doc(order._id).update({
					order_express_datas: response.datas
				});
			}
		}

		return response;
	}

	// 售后列表
	async aftersaleList() {
		// 售后列表
		let response = {
			code: 1,
			datas: []
		};

		const start = Date.now();
		const {
			page,
			rows,
			group,
			state,
			order_id,
			type,
			member_name,
			is_delete,
			begin_time,
			end_time
		} = this.ctx.data;

		const where_obj = {};

		if (state != '全部') {
			where_obj.state = state;
		}

		if (order_id) {
			where_obj.order_id = new RegExp(this.service.utils.filterRegexpKey(order_id), 'i');
		}

		if (type) {
			where_obj.type = type;
		}

		if (member_name) {
			where_obj.member_name = new RegExp(this.service.utils.filterRegexpKey(member_name), 'i');
		}

		if (is_delete !== '') {
			where_obj.is_delete = is_delete;
		}

		if (begin_time && end_time) {
			where_obj.create_time = dbcmd.gte(begin_time).and(dbcmd.lte(end_time));
		}

		let groupWhereObj = Object.assign({}, where_obj);
		delete groupWhereObj[group.field];

		const groupRes = await this.db.collection('usemall-order-aftersale')
			.aggregate()
			.match(groupWhereObj)
			.group({
				_id: '$' + group.field,
				cnt: $.sum(1)
			})
			.end();

		if (groupRes && groupRes.data) {
			response.groupDatas = groupRes.data;
			group.datas = [];
			group.total = 0;

			for (let key in group.obj) {
				group.obj[key] = 0;
			}

			response.groupDatas.forEach(x => {
				if (Object.keys(group.obj).includes(x._id + "")) {
					group.obj[x._id] = x.cnt;
					group.total += x.cnt;
				}
			})
			if (Object.keys(group.obj).includes('全部')) {
				group.obj['全部'] = group.total;
			}

			for (let key in group.obj) {
				group.datas.push({
					name: key,
					cnt: group.obj[key]
				})
			}
			response.group = group;
		}

		const countRes = await this.db.collection('usemall-order-aftersale').where(where_obj).count();
		response.total = countRes.total;

		const aftersaleRes = await this.db.collection('usemall-order-aftersale')
			.where(where_obj)
			.orderBy('create_time', 'desc')
			.skip((page - 1) * rows)
			.limit(rows)
			.get();

		const datas = [];
		const ids = aftersaleRes.data.map(x => x.order_id);
		if (ids.length) {
			const orderRes = await this.db.collection('usemall-order')
				.where({
					order_id: dbcmd.in(ids)
				})
				.orderBy('create_time', 'desc')
				.skip((page - 1) * rows)
				.limit(rows)
				.get();

			const orderDetailsRes = await this.db.collection('usemall-order-detail').where({
				order_id: dbcmd.in(ids)
			}).get();

			aftersaleRes.data.forEach(x => {
				datas.push({
					order: orderRes.data.find(d => d.order_id == x.order_id),
					orderDetails: orderDetailsRes.data.filter(d => d.order_id == x
						.order_id && (d.goods_id == x.goods_id || !x.goods_id) && (d
							.goods_sku_id == x.goods_sku_id || !x.goods_sku_id)),
					aftersale: x
				})
			});
		}
		response.datas = datas;

		const end = Date.now();
		console.log(`耗时：${end - start}ms`);
		response.code = 0;
		response.duration = `耗时：${end - start}ms`;
		return response;
	}

	// 售后删除
	async aftersaleRemove() {
		const response = {
			code: 1,
			msg: ''
		};

		const {
			id
		} = this.ctx.data;

		// 删除
		await this.db.collection('usemall-order-aftersale').where({
			_id: id,
			is_delete: 1
		}).remove();

		response.code = 0;
		response.msg = '删除成功';
		return response;
	}

	// 售后批量删除
	async aftersaleRemoves() {
		const response = {
			code: 1,
			msg: ''
		};

		const {
			ids
		} = this.ctx.data;

		// 批量删除
		await this.db.collection('usemall-order-aftersale').where({
			_id: dbcmd.in(ids),
			is_delete: 1
		}).remove();

		response.code = 0;
		response.msg = `删除成功×${ids.length}`;
		return response;
	}

	// v2.0.6 同意退款
	async refund() {
		let response = {
			code: 1,
		};

		const start = Date.now();
		const nowdate = start;

		const {
			id,
			order_id,
			rebate, // 单位元
			remark,
			state
		} = this.ctx.data;

		const uid = this.ctx.auth.uid;

		let where_obj = {
			is_delete: 0,
			state: '售后中',
			order_id: order_id,
		};

		// 1. 获取订单数据
		let orderRes = await this.db.collection('usemall-order')
			.where(where_obj)
			.field({
				order_actural_paid: true,
				order_id: true,
				state: true,
				is_fxs: true,
				is_settlement: true,
				order_fxs_uid: true,
				order_fxs_amount: true,
				order_member_name: true,
				order_member_openid: true,
				order_member_headimg: true,
				order_info: true,
				order_goods_cnt: true,
				out_trade_no: true,
				order_from: true,
				order_pay_way: true,
				create_uid: true,
			})
			.get();

		if (!(orderRes && orderRes.data && orderRes.data.length == 1)) {
			response.msg = `售后订单[${order_id}]不存在`;
			return response;
		}
		const order = orderRes.data[0];

		// 退款金额
		const refundFee = parseInt(rebate * 100);

		if (order.order_pay_way == '微信支付') {
			const fs = require('fs');
			const path = require('path');

			let wxpayConfig;
			if (order.order_from == 'app') {
				// APP 微信支付
				wxpayConfig = uidConfig.config('app.wxpay');
			} else if (order.order_from == '微信公众号') {
				// 微信公众号 微信支付
				wxpayConfig = uidConfig.config('h5-weixin.pay');
			} else {
				// 微信小程序 微信支付
				wxpayConfig = uidConfig.config('mp-weixin.pay');
			}

			const wxOptions = {
				...wxpayConfig,
				pfx: fs.readFileSync(path.resolve(__dirname, 'cert/wxpay/apiclient_cert.p12')),
				passphrase: 'password'
			}
			const uniWxpayIns = uidPay.initWeixin(wxOptions);
			const refundRes = await uniWxpayIns.refund({
				outTradeNo: order.out_trade_no,
				outRefundNo: order.out_trade_no,
				totalFee: order.order_actural_paid,
				refundFee: refundFee
			});

			if (refundRes.returnCode != 'SUCCESS') {
				response.msg = refundRes.returnMsg;
				return response;
			}
		} else {
			await this.db.collection('usemall-member').doc(order.create_uid).update({
				// 退回用户零钱
				member_amount: this.db.command.inc(refundFee)
			});

			await this.db.collection('usemall-member-money-log').add({
				order_id: order_id,
				money: refundFee,
				money_fmt: '+' + rebate,
				source: '订单退款',
				type: '退款',
				remark: `订单退款+${rebate}`,
				ip: this.ctx.context.CLIENTIP,
				is_delete: 0,
				create_uid: order.create_uid,
				create_time: nowdate
			});
		}

		// 2. 修改订单数据
		const orderUpdateRes = await this.db.collection('usemall-order')
			.doc(order._id)
			.update({
				state: '已售后',
				aftersale_state: 2,
				order_refund_state: state,
				order_pay_state: state,
				last_modify_time: nowdate,
				last_modify_uname: this.ctx.auth.userInfo.username,
				last_modify_uid: uid
			});

		if (orderUpdateRes && orderUpdateRes.updated == 1) {
			const orderDetailRes = await this.db.collection('usemall-order-detail')
				.where({
					order_id: order.order_id
				}).field({
					goods_id: true,
					goods_sku: true,
					goods_num: true
				}).get();

			for (var i = 0; i < orderDetailRes.data.length; i++) {
				let x = orderDetailRes.data[i];

				// 释放库存
				await this.db.collection('usemall-goods').doc(x.goods_id).update({
					stock_num: dbcmd.inc(x.goods_num),
					sale_cnt: dbcmd.inc(-x.goods_num)
				})

				// 释放SKU库存
				if (x.goods_sku) {
					await this.db.collection('usemall-goods-sku').where({
						goods_id: x.goods_id,
						goods_sku: x.goods_sku
					}).update({
						stock_num: dbcmd.inc(x.goods_num),
						sale_cnt: dbcmd.inc(-x.goods_num)
					})
				}
			}

			// 3. 修改退款申请数据 
			const refundUpdateRes = await this.db.collection('usemall-order-refund')
				.doc(id)
				.update({
					state: state,
					remark: remark,
					last_modify_time: nowdate,
					last_modify_uname: this.ctx.auth.userInfo.username,
					last_modify_uid: uid
				});

			// 4. 插入订单日志
			await this.db.collection('usemall-order-log').add({
				order_id: order.order_id,
				log_type: '退款处理',
				current_state: '售后结束',
				prev_state: order.state,
				ip: this.ctx.context.CLIENTIP,
				is_delete: 0,
				create_uid: uid,
				create_uname: this.ctx.auth.userInfo.username,
				create_time: nowdate
			});

			// 5. 修改用户消费金额
			const memberRes = await this.db.collection('usemall-member').doc(order.create_uid).update({
				member_monetary: this.db.command.inc(-refundFee)
			});
		}

		response.datas = orderUpdateRes;

		const end = new Date().getTime();
		console.log(`耗时：${end - start}ms`);
		response.code = 0;
		response.msg = `耗时：${end - start}ms`;
		return response;
	}

	// v2.0.6 拒绝退款
	async refuse() {
		let response = {
			code: 1,
		};

		const start = Date.now();
		const nowdate = start;

		const {
			id,
			order_id,
			remark,
			state
		} = this.ctx.data;

		const uid = this.ctx.auth.uid;

		let where_obj = {
			is_delete: 0,
			state: '售后中',
			order_id: order_id,
		};

		// 1. 获取订单数据
		let orderRes = await this.db.collection('usemall-order')
			.where(where_obj)
			.field({
				order_actural_paid: true,
				order_id: true,
				state: true,
				is_fxs: true,
				is_settlement: true,
				order_fxs_uid: true,
				order_fxs_amount: true,
				order_member_name: true,
				order_member_openid: true,
				order_member_headimg: true,
				order_info: true,
				order_goods_cnt: true,
				create_uid: true,
			})
			.get();

		if (!(orderRes && orderRes.data && orderRes.data.length == 1)) {
			response.msg = `售后订单[${order_id}]不存在`;
			return response;
		}
		const order = orderRes.data[0];

		// 2. 修改订单数据
		const orderUpdateRes = await this.db.collection('usemall-order')
			.doc(order._id)
			.update({
				state: '售后结束',
				order_refund_state: state,
				order_refund_remark: remark,
				last_modify_time: nowdate,
				last_modify_uname: this.ctx.auth.userInfo.username,
				last_modify_uid: uid
			});

		if (orderUpdateRes && orderUpdateRes.updated == 1) {

			// 3. 修改退款申请数据 
			const refundUpdateRes = await this.db.collection('usemall-order-refund')
				.doc(id)
				.update({
					state: state,
					remark: remark,
					last_modify_time: nowdate,
					last_modify_uname: this.ctx.auth.userInfo.username,
					last_modify_uid: uid
				});

			// 4. 插入订单日志
			await this.db.collection('usemall-order-log').add({
				order_id: order.order_id,
				log_type: '退款处理',
				current_state: '售后结束',
				prev_state: order.state,
				ip: this.ctx.context.CLIENTIP,
				is_delete: 0,
				create_uid: uid,
				create_uname: this.ctx.auth.userInfo.username,
				create_time: nowdate
			});
		}

		response.datas = orderUpdateRes;

		const end = new Date().getTime();
		console.log(`耗时：${end - start}ms`);
		response.code = 0;
		response.msg = `耗时：${end - start}ms`;
		return response;
	}

	// 同意售后
	async consentAftersale() {
		const response = {
			code: 1,
		};

		const start = Date.now();
		const nowdate = start;

		const {
			id,
			rebate, // 申请退款情况下 退款金额，单位元
			return_addr // 退货、换货 寄回地址
		} = this.ctx.data;

		const uid = this.ctx.auth.uid;

		// 查询售后数据
		const aftersaleRes = await this.db.collection('usemall-order-aftersale')
			.doc(id)
			.get();
		const [aftersale] = aftersaleRes.data;

		if (!(aftersale && aftersale._id)) {
			response.msg = `售后[${id}]不存在`;
			return response;
		}

		if (['已拒绝', '已完成', '已取消'].includes(aftersale.state)) {
			response.msg = `售后${aftersale.state}`;
			return response;
		}

		try {
			const userRes = await this.db.collection('uni-id-users').doc(aftersale.create_uid).field({
				wx_openid: true,
				wx_unionid: true
			}).get();
			const [user] = userRes.data;

			let openid = '';
			if (user && user.wx_openid) {
				openid = user.wx_openid['h5-weixin'];
			}

			const msg_req = {
				title: `申请${aftersale.type}`,
				type: `${aftersale.type}`,
				reason: `申请${aftersale.type}已同意，请及时寄回`,
				status: '已同意',
				remark: '查看详情'
			};
			switch (aftersale.type) {
				case '退货':
					msg_req.scene = 206;
					break;
				case '换货':
					msg_req.scene = 209;
					break;
			}

			if (aftersale.type != '退款') {
				// 消息通知
				// 不需要 await，只需发送请求即可
				uniCloud.httpclient.request(`${uidConfig.config('message-notify.url')}/aftersale`, {
					method: 'post',
					headers: {
						'message-notify-key': uidConfig.config('message-notify.key')
					},
					data: {
						id: aftersale._id,
						uid: aftersale.create_uid,
						openid: openid,
						...msg_req
					},
					contentType: 'json',
					dataType: 'json'
				});
			}
		} catch (e) {
			console.log('message-notify err', e);
		}

		// 修改售后
		const aftersaleUpdateObj = {
			remark: `同意${aftersale.type}`
		};

		// 修改订单详情
		const orderDetailUpdateObj = {
			aftersale: {
				state: ''
			}
		};

		switch (aftersale.type) {
			case '退款':
				// 同意退款
				await this.aftersaleRefund(uid, aftersale, rebate);
				aftersaleUpdateObj.state = '已完成';
				aftersaleUpdateObj.remark = '同意退款';
				aftersaleUpdateObj.refund_rebate = parseInt(rebate * 100);
				// 已完成
				orderDetailUpdateObj.aftersale.state = '已完成';
				orderDetailUpdateObj.aftersale_state = 2;
				break;
			case '退货':
			case '换货':
				aftersaleUpdateObj.state = '待买家处理';
				aftersaleUpdateObj.sub_state = '待寄回';

				aftersaleUpdateObj.remark = `同意${aftersale.type}，待寄回${aftersale.type}商品`;

				// 寄回地址
				aftersaleUpdateObj.return_addr = return_addr;

				// 待寄回
				orderDetailUpdateObj.aftersale.state = '待寄回';

				// 查询售后订单
				const orderRes = await this.db.collection('usemall-order').where({
						order_id: aftersale.order_id
					})
					.field({
						state: true
					})
					.limit(1)
					.get();

				const [order] = orderRes.data;

				// 写入日志
				await this.db.collection('usemall-order-log').add({
					order_id: aftersale.order_id,
					log_type: `同意${aftersale.type}`,
					current_state: order.state,
					prev_state: order.state,
					remark: '',
					ip: this.ctx.context.CLIENTIP,
					is_delete: 0,
					create_uid: uid,
					create_uname: this.ctx.auth.userInfo.username,
					create_time: nowdate
				});

				break;
		}

		const logObj = {
			type: `同意${aftersale.type}`,
			remark: aftersaleUpdateObj.remark,
			ip: this.ctx.context.CLIENTIP,
			time: nowdate
		};

		// 修改售后数据
		const res = await this.db.collection('usemall-order-aftersale').doc(id).update({
			...aftersaleUpdateObj,

			logs: this.db.command.push(logObj),

			version: this.db.command.inc(1),
			last_modify_time: nowdate,
			last_modify_uname: this.ctx.auth.userInfo.username,
			last_modify_uid: uid
		});

		// 修改售后订单详情
		await this.db.collection('usemall-order-detail').where({
			order_id: aftersale.order_id,
			aftersale_id: aftersale._id,
			aftersale_state: 1
		}).update(orderDetailUpdateObj);

		response.datas = res;

		const end = new Date().getTime();
		console.log(`耗时：${end - start}ms`);
		response.code = 0;
		response.msg = `耗时：${end - start}ms`;
		return response;
	}

	// 售后同意退款
	async aftersaleRefund(uid, aftersale, rebate) {
		const nowdate = Date.now();

		// 1. 获取订单数据
		const orderRes = await this.db.collection('usemall-order')
			.where({
				order_id: aftersale.order_id
			})
			.field({
				order_actural_paid: true,
				order_id: true,
				state: true,

				aftersale_id: true,
				aftersale_state: true,
				aftersale_pre_state: true,

				order_refund_state: true,
				order_refund_amount: true,

				is_fxs: true,
				is_settlement: true,
				order_fxs_uid: true,
				order_fxs_amount: true,
				order_member_name: true,
				order_member_openid: true,
				order_member_headimg: true,
				order_info: true,
				order_goods_cnt: true,
				out_trade_no: true,
				order_from: true,
				order_pay_way: true,
				create_uid: true,
			})
			.get();

		const [order] = orderRes.data;

		if (!(order && order._id)) {
			this.throw(`售后订单[${aftersale.order_id}]不存在`);
		}

		// 获取订单详情
		const orderDetailRes = await this.db.collection('usemall-order-detail').where({
			order_id: order.order_id
		}).get();
		const orderDetails = orderDetailRes.data;

		// 退款金额
		const refundFee = parseInt(rebate * 100);

		if (refundFee > order.order_actural_paid) {
			this.throw(`退款金额[${rebate}]超过实付款金额[${order.order_actural_paid / 100}]`);
		}

		// 处理退款金额，自动退回退款
		if (rebate > 0) {
			switch (order.order_pay_way) {
				case '微信支付':
					const fs = require('fs');
					const path = require('path');

					let wxpayConfig;
					if (order.order_from == 'app') {
						// APP 微信支付
						wxpayConfig = uidConfig.config('app.wxpay');
					} else if (order.order_from == '微信公众号') {
						// 微信公众号 微信支付
						wxpayConfig = uidConfig.config('h5-weixin.pay');
					} else {
						// 微信小程序 微信支付
						wxpayConfig = uidConfig.config('mp-weixin.pay');
					}

					const wxOptions = {
						...wxpayConfig,
						pfx: fs.readFileSync(path.resolve(__dirname, 'cert/wxpay/apiclient_cert.p12')),
						passphrase: 'password'
					}
					const uniWxpayIns = uidPay.initWeixin(wxOptions);
					const refundRes = await uniWxpayIns.refund({
						outTradeNo: order.out_trade_no,
						outRefundNo: aftersale._id,
						totalFee: order.order_actural_paid,
						refundFee: refundFee
					});

					if (refundRes.returnCode != 'SUCCESS') {
						this.throw(refundRes.returnMsg)
					}
					break;
				case '支付宝支付':
					let alipayConfig;
					if (order.order_from == 'app') {
						alipayConfig = uidConfig.config('app.alipay');
					} else {
						alipayConfig = uidConfig.config('mp-alipay.pay');
					}

					const uniAlipayIns = uidPay.initAlipay(alipayConfig);
					const refundAlipayRes = await uniAlipayIns.refund({
						outTradeNo: order.out_trade_no,
						outRefundNo: aftersale._id,
						totalFee: order.order_actural_paid,
						refundFee: refundFee
					});

					if (refundAlipayRes.msg != 'Success') {
						this.throw(refundAlipayRes.msg);
					}
					break;
				case '零钱支付':
					await this.db.collection('usemall-member').doc(order.create_uid).update({
						// 退回用户零钱
						member_amount: this.db.command.inc(refundFee)
					});

					await this.db.collection('usemall-member-money-log').add({
						order_id: order.order_id,
						money: refundFee,
						money_fmt: '+' + rebate,
						source: '订单退款',
						type: '退款',
						remark: `订单退款+${rebate}`,
						ip: this.ctx.context.CLIENTIP,
						is_delete: 0,
						create_uid: order.create_uid,
						create_time: nowdate
					});
					break;
				default:
					this.throw(`${order.order_pay_way}未支持自动退款到账`);
					break;
			}

			// 修改用户消费金额
			const memberRes = await this.db.collection('usemall-member').doc(order.create_uid).update({
				member_monetary: this.db.command.inc(-refundFee)
			});
		}

		try {
			const userRes = await this.db.collection('uni-id-users').doc(aftersale.create_uid).field({
				wx_openid: true,
				wx_unionid: true
			}).get();
			const [user] = userRes.data;

			let openid = '';
			if (user && user.wx_openid) {
				openid = user.wx_openid['h5-weixin'];
			}

			const msg_req = {
				title: `申请${aftersale.type}`,
				type: `${aftersale.type}`,
				reason: `申请${aftersale.type}已退款，请注意查看`,
				status: '已退款',
				remark: '查看详情'
			};
			switch (aftersale.type) {
				case '退款':
					msg_req.scene = 204;
					break;
				case '退货':
					msg_req.scene = 208;
					break;
			}

			// 消息通知
			// 不需要 await，只需发送请求即可
			uniCloud.httpclient.request(`${uidConfig.config('message-notify.url')}/aftersale`, {
				method: 'post',
				headers: {
					'message-notify-key': uidConfig.config('message-notify.key')
				},
				data: {
					id: aftersale._id,
					uid: aftersale.create_uid,
					openid: openid,
					...msg_req
				},
				contentType: 'json',
				dataType: 'json'
			});
		} catch (e) {
			console.log('message-notify err', e);
		}

		// 退款情况
		let remark = '';
		// 2. 修改订单数据
		const orderUpdateObj = {
			// 累计退款金额
			order_refund_amount: this.db.command.inc(refundFee)
		};

		// 退款金额 == 实付款金额
		order.order_refund_amount = order.order_refund_amount || 0;
		if (order.order_refund_amount + refundFee === order.order_actural_paid) {
			orderUpdateObj.order_refund_state = '已退款';
			remark = '已退款，退款金额' + rebate;
		} else {
			orderUpdateObj.order_refund_state = '部分退款';
			remark = '部分退款，退款金额' + rebate;
		}

		// 整单售后情况下，状态修改为 已完成
		if ([101, 201].includes(aftersale.scene)) {
			// 售后场景为 101整单申请退款 201整单申请退货
			orderUpdateObj.state = '已完成';

			// 已完成售后
			orderUpdateObj.aftersale_state = 2;
		} else if (orderDetails.length - 1 === orderDetails.filter(x => x.aftersale_state === 2).length) {
			// 整单已售后
			// 比如 A订单购买了两款商品，A1商品已售后、目前处理A2商品场景下
			// 比如 A订单购买了n款商品，A1 ~ A(n-1)商品已售后、目前处理A(n)商品场景下
			orderUpdateObj.state = '已完成';

			// 已完成售后
			orderUpdateObj.aftersale_state = 2;
		}

		const orderUpdateRes = await this.db.collection('usemall-order')
			.doc(order._id)
			.update({
				...orderUpdateObj,

				last_modify_time: nowdate,
				last_modify_uname: this.ctx.auth.userInfo.username,
				last_modify_uid: uid
			});

		if (orderUpdateRes && orderUpdateRes.updated == 1) {
			for (let i = 0; i < orderDetails.length; i++) {
				const x = orderDetails[i];

				// 整单退款 或 部分商品退款
				if ([101, 201].includes(aftersale.scene) || (x.goods_id === aftersale.goods_id && (x
						.goods_sku_id === aftersale.goods_sku_id || !aftersale.goods_sku_id))) {
					// 释放库存
					await this.db.collection('usemall-goods').doc(x.goods_id).update({
						stock_num: dbcmd.inc(x.goods_num),
						sale_cnt: dbcmd.inc(-x.goods_num)
					})

					// 释放SKU库存
					if (x.goods_sku_id) {
						await this.db.collection('usemall-goods-sku').where({
							_id: x.goods_sku_id,
							goods_id: x.goods_id
						}).update({
							stock_num: dbcmd.inc(x.goods_num),
							sale_cnt: dbcmd.inc(-x.goods_num)
						})
					}
				}
			}

			// 4. 插入订单日志
			await this.db.collection('usemall-order-log').add({
				order_id: order.order_id,
				log_type: `${aftersale.type}完成`,
				remark: remark,
				current_state: orderUpdateObj.state || order.state,
				prev_state: order.state,
				ip: this.ctx.context.CLIENTIP,
				is_delete: 0,
				create_uid: uid,
				create_uname: this.ctx.auth.userInfo.username,
				create_time: nowdate
			});
		}

		return orderUpdateRes;
	}

	// 拒绝售后
	async refuseAftersale() {
		const response = {
			code: 1,
		};

		const start = Date.now();
		const nowdate = start;

		const {
			id,
			reason
		} = this.ctx.data;

		const uid = this.ctx.auth.uid;

		const aftersaleRes = await this.db.collection('usemall-order-aftersale').doc(id).get();
		const [aftersale] = aftersaleRes.data;

		if (!(aftersale && aftersale._id)) {
			response.msg = '售后ID不存在';
			return response;
		}

		if (['已拒绝', '已完成', '已取消'].includes(aftersale.state)) {
			response.msg = `售后${aftersale.state}`;
			return response;
		}

		response.datas = await this.__refuseOrderAftersale(uid, aftersale, reason, `商家拒绝${aftersale.type}申请`);

		const end = new Date().getTime();
		console.log(`耗时：${end - start}ms`);
		response.code = 0;
		response.msg = `耗时：${end - start}ms`;
		return response;
	}

	// 拒绝售后
	async __refuseOrderAftersale(uid, aftersale, reason, remark) {
		// aftersale.state 		状态 	待处理|待买家处理|待卖家处理|已拒绝|已完成|已取消
		// aftersale.sub_state 	子状态 	待寄回|待收货|待发货|待签收
		if (['待买家处理', '已拒绝', '已完成', '已取消'].includes(aftersale.state)) {
			this.throw(`当前售后[${aftersale.state}]，禁止拒绝`);
		}

		try {
			const userRes = await this.db.collection('uni-id-users').doc(aftersale.create_uid).field({
				wx_openid: true,
				wx_unionid: true
			}).get();
			const [user] = userRes.data;

			let openid = '';
			if (user && user.wx_openid) {
				openid = user.wx_openid['h5-weixin'];
			}

			const msg_req = {
				title: `申请${aftersale.type}`,
				type: `${aftersale.type}`,
				reason: `原因：${reason}`,
				status: '已拒绝',
				remark: '查看详情'
			};
			switch (aftersale.type) {
				case '退款':
					msg_req.scene = 205;
					break;
				case '退货':
					msg_req.scene = 207;
					break;
				case '换货':
					msg_req.scene = 210;
					break;
			}

			// 消息通知
			// 不需要 await，只需发送请求即可
			uniCloud.httpclient.request(`${uidConfig.config('message-notify.url')}/aftersale`, {
				method: 'post',
				headers: {
					'message-notify-key': uidConfig.config('message-notify.key')
				},
				data: {
					id: aftersale._id,
					uid: aftersale.create_uid,
					openid: openid,
					...msg_req
				},
				contentType: 'json',
				dataType: 'json'
			});
		} catch (e) {
			console.log('message-notify err', e);
		}

		/**
		 * 1. 售后状态修改为 已拒绝、子状态 置空、备注说明
		 * 2. 修改售后中订单状态为 prev 状态值
		 * 3. 修改订单详情售后状态
		 */

		const nowdate = Date.now();
		const state = '已拒绝';

		remark = (remark || `商家拒绝${aftersale.type}申请`) + ` 原因：${reason}`;

		const updateRes = await this.db.collection('usemall-order-aftersale')
			.doc(aftersale._id)
			.update({
				state: state,
				sub_state: '',
				logs: this.db.command.push({
					type: `拒绝${aftersale.type}`,
					remark: remark,
					ip: this.ctx.context.CLIENTIP,
					time: nowdate
				}),

				remark: remark,
				last_modify_time: nowdate,
				last_modify_uid: uid,
			});

		if (updateRes && updateRes.updated) {
			// 拒绝售后成功
			// 查询售后订单
			const orderRes = await this.db.collection('usemall-order').where({
					order_id: aftersale.order_id
				})
				.field({
					state: true,
					aftersale_id: true,
					aftersale_state: true,
					aftersale_pre_state: true,
					aftersale_cnt: true,
					order_refund_state: true,

					order_id: true,
					create_uid: true,
					order_member_name: true,
					order_expire_time: true
				})
				.limit(1)
				.get();
			const [order] = orderRes.data;

			if (order && order._id) {
				order.aftersale_cnt -= 1;
				if (order.aftersale_cnt <= 0) order.aftersale_cnt = 0;

				const orderUpdateObj = {
					aftersale_state: order.aftersale_cnt ? order.aftersale_state : 0,
					aftersale_cnt: order.aftersale_cnt,
				};
				if (order.state == '售后中') {
					orderUpdateObj.state = order.aftersale_pre_state;
					orderUpdateObj.aftersale_pre_state = '';
					orderUpdateObj.order_aftersale = {
						state: ''
					};
				}
				if (order.order_refund_state == '待处理') {
					orderUpdateObj.order_refund_state = '';
				}

				// 修改售后中订单状态、售后状态
				await this.db.collection('usemall-order')
					.doc(order._id)
					.update({
						...orderUpdateObj,

						last_modify_time: nowdate,
						last_modify_uid: uid
					});

				if (order.state == '售后中') {
					// 写入日志
					await this.db.collection('usemall-order-log').add({
						order_id: order.order_id,
						log_type: `拒绝${aftersale.type}`,
						current_state: order.aftersale_pre_state,
						prev_state: '售后中',
						remark: remark,
						ip: this.ctx.context.CLIENTIP,
						is_delete: 0,
						create_uid: uid,
						create_time: nowdate
					});
				} else {
					// 写入日志
					await this.db.collection('usemall-order-log').add({
						order_id: order.order_id,
						log_type: `拒绝${aftersale.type}`,
						current_state: order.state,
						prev_state: order.state,
						remark: remark,
						ip: this.ctx.context.CLIENTIP,
						is_delete: 0,
						create_uid: uid,
						create_time: nowdate
					});
				}
			}

			// 修改订单明细
			const orderDetailWhere = {
				order_id: aftersale.order_id,
				aftersale_id: aftersale._id,
				aftersale_state: 1
			};

			// 修改售后中订单状态、售后状态
			await this.db.collection('usemall-order-detail')
				.where(orderDetailWhere)
				.update({
					aftersale_state: 0,
					aftersale: {
						state: state
					}
				});
		}

		return updateRes;
	}

	// 售后确定收货
	async consignee() {
		let response = {
			code: 1,
		};

		const start = Date.now();
		const nowdate = start;

		const {
			id,
			rebate, // 单位元
			express,
			express_com,
			express_no,
			remark
		} = this.ctx.data;
		const uid = this.ctx.auth.uid;

		// 查询售后数据
		const aftersaleRes = await this.db.collection('usemall-order-aftersale')
			.doc(id)
			.get();
		const [aftersale] = aftersaleRes.data;

		if (!(aftersale && aftersale._id)) {
			response.msg = `售后[${id}]不存在`;
			return response;
		}

		if (['已拒绝', '已完成', '已取消'].includes(aftersale.state)) {
			response.msg = `售后${aftersale.state}`;
			return response;
		}

		try {
			const userRes = await this.db.collection('uni-id-users').doc(aftersale.create_uid).field({
				wx_openid: true,
				wx_unionid: true
			}).get();
			const [user] = userRes.data;

			let openid = '';
			if (user && user.wx_openid) {
				openid = user.wx_openid['h5-weixin'];
			}

			const msg_req = {
				title: `申请${aftersale.type}`,
				type: `${aftersale.type}`,
				reason: `换货已邮寄`,
				status: '已邮寄',
				remark: '查看详情'
			};
			switch (aftersale.type) {
				case '换货':
					msg_req.scene = 211;
					break;
			}

			if (aftersale.type != '退货') {
				// 消息通知
				// 不需要 await，只需发送请求即可
				uniCloud.httpclient.request(`${uidConfig.config('message-notify.url')}/aftersale`, {
					method: 'post',
					headers: {
						'message-notify-key': uidConfig.config('message-notify.key')
					},
					data: {
						id: aftersale._id,
						uid: aftersale.create_uid,
						openid: openid,
						...msg_req
					},
					contentType: 'json',
					dataType: 'json'
				});
			}
		} catch (e) {
			console.log('message-notify err', e);
		}

		// 修改售后
		const aftersaleUpdateObj = {
			remark: `${aftersale.type}确认收货`
		};

		// 修改订单详情
		const orderDetailUpdateObj = {
			aftersale: {
				state: ''
			}
		};

		switch (aftersale.type) {
			case '退货':
				// 确认收货并退款
				await this.aftersaleRefund(uid, aftersale, rebate);
				aftersaleUpdateObj.state = '已完成';
				aftersaleUpdateObj.sub_state = '';
				aftersaleUpdateObj.remark = '商家确认收货并退款';
				aftersaleUpdateObj.refund_rebate = parseInt(rebate * 100);
				// 已完成
				orderDetailUpdateObj.aftersale.state = '已完成';
				orderDetailUpdateObj.aftersale_state = 2;
				break;
			case '换货':
				aftersaleUpdateObj.state = '待买家处理';
				aftersaleUpdateObj.sub_state = '待签收';

				aftersaleUpdateObj.remark = `商家确认收货并发货`;

				let phone = '';
				if (aftersale && aftersale.exchange_addr && aftersale.exchange_addr.mobile) {
					phone = aftersale.exchange_addr.mobile;
				}

				// 发货的快递信息
				aftersaleUpdateObj.exchange_express = {
					express: express,
					com: express_com,
					no: express_no,
					phone: phone,
					remark: remark
				};

				// 待买家处理
				orderDetailUpdateObj.aftersale.state = '待买家处理';

				// 释放库存，换货确认收货的情况下，释放对应商品SKU库存
				const orderDetailRes = await this.db.collection('usemall-order-detail').where({
					order_id: aftersale.order_id,
					aftersale_id: aftersale._id,
					aftersale_state: 1
				}).get();

				const orderDetails = orderDetailRes.data || [];
				for (let i = 0; i < orderDetails.length; i++) {
					const x = orderDetails[i];

					// 释放库存
					await this.db.collection('usemall-goods').doc(x.goods_id).update({
						stock_num: dbcmd.inc(x.goods_num),
						sale_cnt: dbcmd.inc(-x.goods_num)
					})

					// 释放SKU库存
					if (x.goods_sku_id) {
						await this.db.collection('usemall-goods-sku').where({
							_id: x.goods_sku_id,
							goods_id: x.goods_id
						}).update({
							stock_num: dbcmd.inc(x.goods_num),
							sale_cnt: dbcmd.inc(-x.goods_num)
						})
					}
				}

				// 查询售后订单
				const orderRes = await this.db.collection('usemall-order').where({
						order_id: aftersale.order_id
					})
					.field({
						state: true
					})
					.limit(1)
					.get();

				const [order] = orderRes.data;

				// 写入日志
				await this.db.collection('usemall-order-log').add({
					order_id: aftersale.order_id,
					log_type: '换货-确认收货并发货',
					current_state: order.state,
					prev_state: order.state,
					remark: '',
					ip: this.ctx.context.CLIENTIP,
					is_delete: 0,
					create_uid: uid,
					create_uname: this.ctx.auth.userInfo.username,
					create_time: nowdate
				});

				break;
		}

		const logObj = {
			type: `${aftersale.type}-确认收货`,
			remark: aftersaleUpdateObj.remark,
			ip: this.ctx.context.CLIENTIP,
			time: nowdate
		};

		// 修改售后数据
		const res = await this.db.collection('usemall-order-aftersale').doc(id).update({
			...aftersaleUpdateObj,

			logs: this.db.command.push(logObj),

			version: this.db.command.inc(1),
			last_modify_time: nowdate,
			last_modify_uname: this.ctx.auth.userInfo.username,
			last_modify_uid: uid
		});

		// 修改售后订单详情
		await this.db.collection('usemall-order-detail').where({
			order_id: aftersale.order_id,
			aftersale_id: aftersale._id,
			aftersale_state: 1
		}).update(orderDetailUpdateObj);

		// 查询售后订单
		const orderRes = await this.db.collection('usemall-order').where({
				order_id: aftersale.order_id
			})
			.field({
				state: true
			})
			.limit(1)
			.get();

		const [order] = orderRes.data;

		response.datas = res;

		const end = new Date().getTime();
		console.log(`耗时：${end - start}ms`);
		response.code = 0;
		response.msg = `耗时：${end - start}ms`;
		return response;
	}

	// 查看售后物流
	async aftersaleExpress() {
		const response = {
			code: 1,
			msg: '物流轨迹查询失败'
		};

		const {
			aftersale_id,
			type // 2售后退换货寄回 3售后换货寄出
		} = this.ctx.data;

		if (!aftersale_id) {
			response.msg = '售后ID不存在';
			return response;
		}

		// 查询订单数据
		const aftersaleRes = await this.db.collection('usemall-order-aftersale').where({
			_id: aftersale_id
		}).field({
			logs: false
		}).get();

		const [aftersale] = aftersaleRes.data;

		if (!(aftersale && aftersale._id)) {
			response.msg = `售后[${id}]不存在`;
			return response;
		}

		// 快递信息
		let express = {};

		switch (type) {
			case 2:
				express = aftersale.return_express;
				break;
			case 3:
				express = aftersale.exchange_express;
				break;
		}

		if (!(express && Object.keys(express).length)) {
			response.msg = '快递单号不存在';
			return response;
		}

		// 调用快递100 实时快递查询接口
		const kd100Res = await this.service.express.kd100Query({
			"com": express.com || this.service.express.getKd100Com(express.com),
			"num": express.no,
			"phone": express.phone
		});

		response.datas = kd100Res;
		response.datas.company = express.com;
		response.msg = response.datas.message;

		if (response.datas && response.datas.message == "ok") {
			response.code = 0;
		}

		return response;
	}
}